package com.candy.codegen.util;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.candy.codegen.config.GenConfig;
import com.candy.codegen.constant.GenConstants;
import com.candy.codegen.domain.entity.GenTable;
import com.candy.codegen.domain.entity.GenTableColumn;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;

import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * 代码生成器工具类
 * @author rong xi
 * @date 2023/09/14 10:27
 * @version 1.0
 */
public class GenUtils {
    /**
     * 初始化表信息
     */
    public static void initTableField(GenTable genTable) {
        genTable.setId(IdUtil.getSnowflakeNextId());
        //
        genTable.setClassName(convertClassName(genTable.getTableName()));
        genTable.setPackageName(GenConfig.instance.getPackageName());
        genTable.setModuleName(getModuleName(GenConfig.instance.getPackageName()));
        genTable.setBusinessName(getBusinessName(genTable.getTableName()));
        genTable.setFunctionName(replaceText(genTable.getTableComment()));
        genTable.setFunctionAuthor(GenConfig.instance.getAuthor());
        genTable.setCreateUser(1L);
        genTable.setCreateTime(LocalDateTime.now());
        genTable.setTplCategory(GenConstants.TPL_CRUD);
        genTable.setGenType(0L);
    }

    /**
     * 初始化列属性字段
     */
    public static void initColumnField(GenTableColumn column, GenTable table) {
        column.setId(IdUtil.getSnowflakeNextId());
        column.setTableId(table.getId());
        column.setCreateUser(table.getCreateUser());
        column.setCreateTime(LocalDateTime.now());
        column.setColumnComment(column.getColumnComment().replace("（","("));
        column.setColumnComment(column.getColumnComment().replace("）",")"));
        //去掉(后面的内容  varchar(255) -> varchar
        String dataType = getDbType(column.getColumnType());
        String columnName = column.getColumnName();
        // 设置java属性名 create_time -> createTime
        column.setJavaField(StrUtil.toCamelCase(columnName));
        // 设置默认类型
        column.setJavaType(GenConstants.TYPE_STRING);
        // 设置默认匹配条件
        column.setQueryType(GenConstants.QUERY_EQ);
        // 插入字段（默认所有字段都需要插入）
        column.setIsInsert(GenConstants.REQUIRE);
        //列表展示字段 （默认所有字段都需要列表展示）
        column.setIsList(GenConstants.REQUIRE);
        //都需要编辑（默认所有字段都需要编辑）
        column.setIsEdit(GenConstants.REQUIRE);
        //都需要查询（默认所有字段都需要编辑）
        column.setIsQuery(GenConstants.REQUIRE);
        //都需要验证（默认所有字段都需要验证）
        column.setIsVerify(GenConstants.REQUIRE);

        //设置get方法
        column.setGetMethod("get"+StrUtil.upperFirst(column.getJavaField())+"()");
        //设置get方法
        column.setSetMethod("set"+StrUtil.upperFirst(column.getJavaField())+"()");
        //设置列大写
        column.setColumnNameUpper(column.getColumnName().toUpperCase());
        //内容长度
        column.setContentLength(getColumnLength(column.getColumnType()));

        //文本类型
        if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) {
            // 字符串长度超过500设置为文本域
            Integer columnLength = getColumnLength(column.getColumnType());
            String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
            column.setHtmlType(htmlType);
        //时间类型
        } else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) {
            column.setJavaType(GenConstants.TYPE_DATE);
            column.setHtmlType(GenConstants.HTML_DATETIME);
        //数字类型
        } else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) {
            column.setHtmlType(GenConstants.HTML_INPUT);
            // 如果是浮点型 统一用BigDecimal

            if (dataType.startsWith("decimal")) {
                column.setJavaType(GenConstants.TYPE_BIG_DECIMAL);
            }else if(dataType.startsWith("bigint")){
                column.setJavaType(GenConstants.TYPE_LONG);
            }else if(dataType.startsWith("tinyint") && column.getContentLength() ==1) {
                column.setJavaType(GenConstants.TYPE_BOOLEAN);
            }else{
                column.setJavaType(GenConstants.TYPE_INTEGER);
            }
        }

        // 公共字段无需编辑和插入和展示和查询
        if (GenConstants.commonFields.contains(column.getColumnName())) {
            column.setIsEdit(GenConstants.NOT_REQUIRE);
            column.setIsInsert(GenConstants.NOT_REQUIRE);
            column.setIsList(GenConstants.NOT_REQUIRE);
            column.setIsQuery(GenConstants.NOT_REQUIRE);
            column.setIsVerify(GenConstants.NOT_REQUIRE);
            column.setIsRequired(GenConstants.NOT_REQUIRE);
        }

        // 主键查询字段
        if (GenConstants.YES.equals(column.getIsPk())) {
            column.setIsQuery(GenConstants.REQUIRE);
            column.setIsList(GenConstants.REQUIRE);
            column.setIsInsert(GenConstants.REQUIRE);
        }

        // 创建时间列表显示
        if ("create_time".equals(column.getColumnName())) {
            column.setIsList(GenConstants.REQUIRE);
        }

        // 查询字段类型 name结尾的字段用like
        if (StringUtils.endsWithIgnoreCase(columnName, "name")) {
            column.setQueryType(GenConstants.QUERY_LIKE);
        }

        // 状态字段设置单选框
        if (StringUtils.endsWithIgnoreCase(columnName, "state")) {
            column.setHtmlType(GenConstants.HTML_RADIO);
        }

        // 类型&性别字段设置下拉框
        else if (StringUtils.endsWithIgnoreCase(columnName, "type")
                || StringUtils.endsWithIgnoreCase(columnName, "sex")) {
            column.setHtmlType(GenConstants.HTML_SELECT);
        }
        // 文件字段设置上传控件
        else if (StringUtils.endsWithIgnoreCase(columnName, "file")) {
            column.setHtmlType(GenConstants.HTML_UPLOAD);
        }
        // 内容字段设置富文本控件
        else if (StringUtils.endsWithIgnoreCase(columnName, "content")) {
            column.setHtmlType(GenConstants.HTML_SUMMERNOTE);
        }
    }

    /**
     * 校验数组是否包含指定值
     *
     * @param arr         数组
     * @param targetValue 值
     * @return 是否包含
     */
    public static boolean arraysContains(String[] arr, String targetValue) {
        return Arrays.asList(arr).contains(targetValue);
    }

    /**
     * 获取模块名
     *
     * @param packageName 包名
     * @return 模块名
     */
    public static String getModuleName(String packageName) {
        int lastIndex = packageName.lastIndexOf(".");
        int nameLength = packageName.length();
        return StringUtils.substring(packageName, lastIndex + 1, nameLength);
    }

    /**
     * 获取业务名
     *
     * @param tableName 表名
     * @return 业务名
     */
    public static String getBusinessName(String tableName) {
        int lastIndex = tableName.lastIndexOf("_");
        int nameLength = tableName.length();
        return StringUtils.substring(tableName, lastIndex + 1, nameLength);
    }

    /**
     * 表名转换成Java类名
     *
     * @param tableName 表名称
     * @return 类名
     */
    public static String convertClassName(String tableName) {
        boolean autoRemovePre = GenConfig.instance.getAutoRemovePre();
        String tablePrefix = GenConfig.instance.getTablePrefix();
        if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) {
            String[] searchList = StringUtils.split(tablePrefix, ",");
            tableName = replaceFirst(tableName, searchList);
        }
        return StringUtils.convertToCamelCase(tableName);
    }

    /**
     * 批量替换前缀
     *
     * @param replacementm 替换值
     * @param searchList   替换列表
     * @return string 结果
     */
    public static String replaceFirst(String replacementm, String[] searchList) {
        String text = replacementm;
        for (String searchString : searchList) {
            if (replacementm.startsWith(searchString)) {
                text = replacementm.replaceFirst(searchString, "");
                break;
            }
        }
        return text;
    }

    /**
     * 关键字替换
     *
     * @param text 需要被替换的名字
     * @return 替换后的名字
     */
    public static String replaceText(String text) {
        return RegExUtils.replaceAll(text, "(?:表|若依)", "");
    }

    /**
     * 获取数据库类型字段
     *
     * @param columnType 列类型
     * @return 截取后的列类型
     */
    public static String getDbType(String columnType) {
        columnType = StrUtil.split(columnType," ").get(0);
        if (StringUtils.indexOf(columnType, "(") > 0) {
            return StringUtils.substringBefore(columnType, "(");
        } else {
            return columnType;
        }
    }

    /**
     * 获取字段长度
     *
     * @param columnType 列类型
     * @return 截取后的列类型
     */
    public static Integer getColumnLength(String columnType) {
        if (StringUtils.indexOf(columnType, "(") > 0) {
            String length = StringUtils.substringBetween(columnType, "(", ")");
            return Integer.valueOf(length);
        } else {
            return 0;
        }
    }


    public static Boolean isSuperColumn(String javaField) {
        return StringUtils.equalsAnyIgnoreCase(javaField,
                // BaseEntity
                "createBy", "createTime", "updateBy", "updateTime", "remark",
                // TreeEntity
                "parentName", "parentId", "orderNum", "ancestors");
    }

    public static boolean isUsableColumn(String javaField) {
        // isSuperColumn()中的名单用于避免生成多余Domain属性，若某些属性在生成页面时需要用到不能忽略，则放在此处白名单
        return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
    }

    public static boolean isSuperColumn(String tplCategory, String javaField) {
        if (isTree(tplCategory)) {
            return StringUtils.equalsAnyIgnoreCase(javaField,
                    ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY));
        }
        return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
    }

    public static boolean isTree(String tplCategory) {
        return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory);
    }

}
